package com.wangc.commons.utils;

import org.apache.commons.lang3.StringUtils;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Calendar;
import java.util.Date;

/**
 * 时间日期工具类
 *
 * @author yaonan
 * @version [版本号, 2020年4月24日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class DateUtils {
    /**
     * 时间转字符串
     *
     * @param date   待转换的时间
     * @param format 转换格式
     * @return 日期字符串
     */
    public static String dateToString(Date date, String format) {
        String result = null;
        if (null == format) {
            format = "yyyy-MM-dd HH:mm:ss";
        }

        if (null != date) {
            DateFormat sdf = new SimpleDateFormat(format);
            result = sdf.format(date);
        }
        return result;
    }

    /**
     * 字符串转为Date
     *
     * @param str
     * @param format
     * @return
     */
    public static Date stringToDate(String str, String format) {
        format = (format == null || format.isEmpty()) ? "yyyy-MM-dd HH:mm:ss" : format;
        DateFormat f = new SimpleDateFormat(format);
        Date date = null;
        try {
            date = f.parse(str);
        } catch (ParseException e) {
            return null;
        }
        return date;
    }

    /**
     * Date转为LocalDate
     *
     * @param date
     * @return
     */
    public static LocalDate dateToLocalDate(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    /**
     * 时间戳秒数转时间
     *
     * @param epochSecond 秒数
     * @return LocalDateTime
     */
    public static LocalDateTime parse(Long epochSecond) {
        return LocalDateTime.ofInstant(Instant.ofEpochSecond(epochSecond), ZoneId.systemDefault());
    }

    /**
     * 时间字符串转时间
     *
     * @param dateStr 时间字符串
     * @param pattern 转换格式
     * @return LocalDateTime
     */
    public static LocalDateTime parse(String dateStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        try {
            return LocalDateTime.parse(dateStr, formatter);
        } catch (DateTimeParseException e) {
            return null;
        }
    }

    /**
     * 时间字符串转时间
     *
     * @param dateStr 时间字符串
     * @param pattern 转换格式
     * @return Date
     */
    public static Date parseToDate(String dateStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        try {
            return Date.from(LocalDateTime.parse(dateStr, formatter).atZone(ZoneId.systemDefault()).toInstant());
        } catch (DateTimeParseException e) {
            return null;
        }
    }

    /**
     * 时间转换为字符串
     *
     * @param localDateTime 转换的时间
     * @param pattern       转换格式
     * @return 时间字符串
     */
    public static String format(LocalDateTime localDateTime, String pattern) {
        try {
            return DateTimeFormatter.ofPattern(pattern).format(localDateTime);
        } catch (DateTimeException e) {
            return StringUtils.EMPTY;
        }
    }

    /**
     * 增加天数
     *
     * @param date 日期
     * @param days 天数
     * @return 增加天数后的日期
     */
    public static Date addDays(Date date, Integer days) {
        return toDate(toLocalDate(date).plusDays(days.longValue()));
    }

    /**
     * localDate to date
     *
     * @param localDate
     * @return Date
     */
    public static Date toDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    /**
     * date to localDate
     *
     * @param date
     * @return LocalDate
     */
    public static LocalDate toLocalDate(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    /**
     * date to localDateTime
     *
     * @param date
     * @return LocalDateTime
     */
    public static LocalDateTime toLocalDateTime(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * 计算相差天数
     *
     * @param begin 开始日期
     * @param end   结束日期
     * @return 相差天数
     */
    public static long between(Date begin, Date end) {
        LocalDate beginDate = toLocalDate(begin);
        LocalDate endDate = toLocalDate(end);
        return endDate.toEpochDay() - beginDate.toEpochDay();
    }

    /**
     * 获取日期当天开始时间
     *
     * @param date
     * @return 当天零点时间
     */
    public static Date dayBegin(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c.getTime();
    }

    /**
     * 获取日期当天结束时间
     *
     * @param date
     * @return 当天23:59:59时间
     */
    public static Date dayEnd(final Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        c.set(Calendar.MILLISECOND, 999);
        return c.getTime();
    }

    /**
     * 功能描述：返回小时
     *
     * @param date 日期
     * @return 返回小时
     */
    public static int getHour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * 功能描述:<br>
     * 获取当前时间返回 Timestamp类型
     *
     * @param
     * @return java.sql.Timestamp
     */
    public static Timestamp getTimestamp_Now() {
        return Timestamp.valueOf(LocalDateTime.now());
    }

    /**
     * 功能描述:<br>
     * 获取当前时间返回 Date类型
     *
     * @param
     * @return java.util.Date
     */
    public static Date getDate_Now() {
        LocalDateTime localDateTime = LocalDateTime.now();
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }
    /**
     * LocalDateTime转换为Date
     *
     * @param localDateTime
     * @return
     */
    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        //Combines this date-time with a time-zone to create a  ZonedDateTime.
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }

    /***
     * 当前系统时间加上指定分钟数
     * @param minutes
     * @return
     */
    public static Date plusMinutes(long minutes) {
        return localDateTimeToDate(LocalDateTime.now().plusMinutes(minutes));
    }
}
